package com.flex.core.scheduling;

import java.lang.reflect.Method;
import java.util.Date;

import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.context.ApplicationContext;

import com.flex.core.scheduling.annotation.Cron;
import com.flex.core.scheduling.annotation.Simple;
import com.flex.service.BatchJobBean;

/**
 * 定时任务工厂类
 * 
 * @author radio
 * 
 */
public class SchedulerFactory {

	private Scheduler sched = null;

	/**
	 * 创建组装定时任务，根据定时任务的配置注解来组装定时任务
	 * 
	 * @param ctx
	 *            spring的应用上下文，用于获得定时任务的service
	 * @return
	 * @throws Exception
	 */
	private Scheduler createScheduler(ApplicationContext ctx) throws Exception {
		BatchJobBean job = (BatchJobBean) ctx.getBean("batchJobBean");
		Method[] methods = job.getClass().getDeclaredMethods();
		for (Method method : methods) {
			String methodName = method.getName();
			String jobDetailName = methodName + ".jobDetail";
			String trigerName = methodName + ".trigger";
			JobDetail jobDetail = null;
			Trigger trigger = null;
			boolean concurrent = true;
			// 简单定时任务
			if (method.isAnnotationPresent(Simple.class)) {
				Simple simpleAnnotation = method.getAnnotation(Simple.class);
				Date startTime = new Date(System.currentTimeMillis()
						+ simpleAnnotation.start());
				trigger = new SimpleTrigger(trigerName, null, startTime, null,
						simpleAnnotation.count(), simpleAnnotation.repeat());
				concurrent = simpleAnnotation.concurrent();
			}
			// 复杂的定时任务
			if (method.isAnnotationPresent(Cron.class)) {
				Cron cronAnnotation = method.getAnnotation(Cron.class);
				trigger = new CronTrigger(trigerName, null, cronAnnotation
						.express());
				concurrent = cronAnnotation.concurrent();
			}
			// 是否并发
			if (concurrent) {
				jobDetail = new JobDetail(jobDetailName, null, JobWrapper.class);
			} else {
				jobDetail = new JobDetail(jobDetailName, null,
						StatefulJobWrapper.class);
			}
			// 将要运行的service类和反射获得的方法存到jobDataMap中
			JobDataMap data = jobDetail.getJobDataMap();
			data.put("jobObject", job);
			data.put("method", method);
			if (trigger != null) {
				sched = StdSchedulerFactory.getDefaultScheduler();
				sched.scheduleJob(jobDetail, trigger);
			}
		}
		return sched;
	}

	/**
	 * 开始定时任务
	 * 
	 * @param ctx
	 * @throws SchedulerException
	 */
	protected void start(ApplicationContext ctx) throws SchedulerException {
		try {
			createScheduler(ctx);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (sched != null) {
			sched.start();
		}
	}

	/**
	 * 关闭定时任务
	 */
	protected void shutdown() {
		try {
			sched.shutdown(true);
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
